/**
 * Project:   warnme-server
 * File:      EventsDaoImpl.java
 * License: 
 *            This file is licensed under GNU General Public License version 3
 *            http://www.gnu.org/licenses/gpl-3.0.txt
 *
 * Copyright: Bartlomiej Gebski [ b.k.gebski@gmail.com ]
 * Date:      Apr 3, 2014
 */

package dtu.ds.warnme.dao.impl;

import java.util.ArrayList;
import java.util.List;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.apache.commons.lang3.ArrayUtils;

import dtu.ds.warnme.dao.EventsDao;
import dtu.ds.warnme.model.impl.EventEntity;
import dtu.ds.warnme.model.impl.EventEntity_;
import dtu.ds.warnme.model.impl.EventType;

/**
 * @author Bartlomiej Gebski
 */
public class EventsDaoImpl extends AbstractGenericDao<EventEntity> implements EventsDao {

	/*
	 * (non-Javadoc)
	 * @see dtu.ds.warnme.dao.EventsDao#getNearestEvents(java.lang.Float, java.lang.Float, java.lang.Float, java.lang.Integer,
	 * dtu.ds.warnme.model.impl.EventType)
	 */
	@Override
	public List<EventEntity> getNearestEvents(Float nLat, Float sLat, Float eLng, Float wLng, EventType... eventTypes) {
		CriteriaBuilder criteriaBuilder = getCriteriaBuilder();
		CriteriaQuery<EventEntity> criteriaQuery = criteriaBuilder.createQuery(EventEntity.class);
		Root<EventEntity> root = criteriaQuery.from(EventEntity.class);

		List<Predicate> predicates = new ArrayList<Predicate>();
		predicates.add(criteriaBuilder.lessThanOrEqualTo(root.get(EventEntity_.latitude), nLat));
		predicates.add(criteriaBuilder.greaterThanOrEqualTo(root.get(EventEntity_.latitude), sLat));
		predicates.add(criteriaBuilder.lessThanOrEqualTo(root.get(EventEntity_.longitude), eLng));
		predicates.add(criteriaBuilder.greaterThanOrEqualTo(root.get(EventEntity_.longitude), wLng));

		if (ArrayUtils.isNotEmpty(eventTypes)) {
			List<Predicate> eventTypePredicates = new ArrayList<Predicate>();
			for (EventType et : eventTypes) {
				eventTypePredicates.add(criteriaBuilder.equal(root.get(EventEntity_.eventType), et));
			}
			predicates.add(criteriaBuilder.and(criteriaBuilder.or(eventTypePredicates.toArray(new Predicate[eventTypePredicates.size()]))));
		}

		criteriaQuery.where(predicates.toArray(new Predicate[predicates.size()]));
		return getAllByCriteria(criteriaQuery);
	}

}
